<script setup lang="ts">
import SectionCard from "@/components/app/section-card.vue";
import { RightOutlined, SettingFilled } from "@ant-design/icons-vue";
import { computed, reactive, ref, watch } from "vue";
import type { LocalVersionItem } from "@/modules/dev-env/common/types.ts";
import path from "@/framework/util/path.ts";
import { message } from "ant-design-vue";
import { showMessageAndPrint } from "@/framework/util/log.ts";
import { execInTerminal } from "@/util/system-utils2.ts";
import ConfirmButton from "@/components/framework/confirm-button.vue";
import WindowsServiceButton from "@/modules/dev-env/components/windows-service-button.vue";
import { ConfigUtils } from "@/util/config-utils.ts";
import { CmdTools } from "@/util/cmd-tools.ts";
import OpenFileButton from "@/modules/dev-env/components/open-file-button.vue";
import type { MariadbEnvStore } from "@/modules/dev-env/database/mariadb/mariadb-env-store.ts";
import type { MariadbDevilConfig } from "@/modules/dev-env/database/mariadb/types.ts";
import FolderPickerInput from "@/components/framework/folder-picker-input.vue";
import { EnvTree, DevilInstallTree } from "@/modules/dev-env/common/tree.ts";

const { store } = defineProps<{
  store: MariadbEnvStore;
}>();

// 当前操作版本
const version = computed<LocalVersionItem | null>(() => store.selectedItem);
// 配置文件路径
const configFilePath = computed(() => (version.value ? path.join(version.value.installPath, DevilInstallTree.configFile) : ""));
// 数据库配置
const myConfig = ref<MariadbDevilConfig>({});
const initConfig = reactive({
  rootPwd: "root",
  port: "3306",
  allowNetworkAccessRoot: false,
});

// my.ini文件路径, 与mysql不同,mariadb的配置文件在data目录下
const myIniPath = computed(() => (myConfig.value.dataDir ? path.join(myConfig.value.dataDir, "my.ini") : ""));

const canRunDbCmd = computed(() => !!myConfig.value.dataDir);

// Windows服务名称
const serviceName = computed(() => myConfig.value.serviceName);
const canRunWinSrv = computed(() => !!myConfig.value.dataDir && !!myConfig.value.serviceName);

const getDefaultDataPath = (version: LocalVersionItem) => {
  const [major, minor] = version.version.split(".");
  return path.join(store.installDir, EnvTree.dataDir, `mariadb-${major}.${minor}`);
};

watch(
  version,
  async value => {
    if (value) {
      const config = (await native.fs.readFileJson<MariadbDevilConfig>(configFilePath.value)) || {};
      config.dataDir ||= getDefaultDataPath(value);
      config.serviceName ||= "MariaDB";
      myConfig.value = config;
    }
  },
  { immediate: true },
);

const saveDevilConfig = () => {
  if (!configFilePath.value) return;
  const configContent = JSON.stringify(myConfig.value, null, 2);
  native.fs.writeFile(configFilePath.value, configContent).catch(showMessageAndPrint);
};

const execCmd = (cmd: string, sudo = false) => {
  execInTerminal(cmd, { cwd: version.value!.installPath, subPath: ["bin"], sudo });
};

const initDatabase = async () => {
  const datadir = myConfig.value.dataDir!;
  const files = await native.fs.readdir(datadir);
  if (files.length > 0) return void message.error("数据目录不为空");

  await native.fs.mkdir(datadir, { recursive: true });

  const cmds = ["mariadb-install-db", `--datadir="${datadir}"`];
  if (initConfig.rootPwd) cmds.push(`--password=${initConfig.rootPwd}`);
  if (initConfig.port) cmds.push(`--port=${initConfig.port}`);
  if (initConfig.allowNetworkAccessRoot) cmds.push("--allow-remote-root-access");
  execCmd(cmds.join(" "));
};

const runMariadbd = () => {
  execCmd(`mariadbd --defaults-file="${myIniPath.value}" --console`);
};

const loginServer = async () => {
  let port = "3306";
  if (await native.fs.exists(myIniPath.value!)) {
    const config = await ConfigUtils.readIni(myIniPath.value!);
    if (config.mysqld?.port) {
      port = config.mysqld.port;
    }
  }

  execCmd(`mariadb -P ${port} -uroot -p`);
};

const installWindowsService = async () => {
  if (await CmdTools.winsrv.exists(serviceName.value!)) {
    return void message.error("服务已安装");
  }
  execCmd(`mariadbd --install ${myConfig.value.serviceName} --defaults-file="${myIniPath.value}"`, true);
  saveDevilConfig();
};

const beforeUninstall = async () => {
  if (!(await CmdTools.winsrv.exists(myConfig.value.serviceName!))) {
    message.error("服务未安装");
    return false;
  }
  return true;
};

const uninstallWindowsService = async () => {
  execCmd(`mariadbd --remove ${myConfig.value.serviceName}`, true);
  if (await native.fs.exists(configFilePath.value)) {
    await native.fs.rm(configFilePath.value);
  }
};
</script>

<template>
  <section-card :icon="SettingFilled">
    <template #title>
      <span>配置/安装</span>
      <span v-if="version" class="color-text-secondary">{{ version.installPath }}</span>
    </template>

    <div v-if="version" class="full-view overflow-y-auto p-10">
      <a-form :label-col="{ span: 5 }" :wrapper-col="{ span: 17 }" :disabled="!version">
        <a-divider orientation="left">
          <span class="color-text-secondary font-14">数据库配置</span>
        </a-divider>

        <a-form-item label="数据目录" required>
          <folder-picker-input v-model:value="myConfig.dataDir" />
        </a-form-item>
        <a-form-item label="root密码">
          <a-input v-model:value="initConfig.rootPwd" placeholder="请输入" allow-clear />
        </a-form-item>
        <a-form-item label="端口">
          <a-input-number v-model:value="initConfig.port" placeholder="请输入" allow-clear class="w-200" />
        </a-form-item>
        <a-form-item label=" " :colon="false">
          <a-checkbox v-model:checked="initConfig.allowNetworkAccessRoot">允许远程登录root</a-checkbox>
        </a-form-item>
        <a-form-item label=" " :colon="false">
          <a-space>
            <a-button :disabled="!canRunDbCmd" @click="initDatabase">初始化数据库</a-button>
            <RightOutlined class="color-text-tertiary" />
            <open-file-button :file="myIniPath" tip="配置文件不存在">编辑配置</open-file-button>
            <RightOutlined class="color-text-tertiary" />
            <a-button :disabled="!canRunDbCmd" @click="runMariadbd">运行mariadbd</a-button>
            <RightOutlined class="color-text-tertiary" />
            <a-button :disabled="!canRunDbCmd" @click="loginServer">登录MariaDB</a-button>
          </a-space>
        </a-form-item>

        <a-divider orientation="left">
          <span class="color-text-secondary font-14">Windows服务</span>
        </a-divider>
        <a-form-item label="服务名称">
          <a-input v-model:value="myConfig.serviceName" placeholder="请输入" allow-clear />
        </a-form-item>
        <a-form-item label=" " :colon="false">
          <a-space>
            <a-button :disabled="!canRunWinSrv" @click="installWindowsService">安装</a-button>
            <confirm-button :disabled="!canRunWinSrv" content="确定要卸载吗？" :before-confirm="beforeUninstall" @ok="uninstallWindowsService"
              >卸载
            </confirm-button>
            <windows-service-button :disabled="!canRunWinSrv" :service-name="myConfig.serviceName" />
            <windows-service-button :disabled="!canRunWinSrv" :service-name="myConfig.serviceName" action="stop" danger />
          </a-space>
        </a-form-item>
      </a-form>
    </div>
    <div v-else class="full flex-center flex-dc">
      <p class="color-text-secondary">请选择配置版本</p>
      <p class="color-text-tertiary">下拉菜单 > "配置/安装"</p>
    </div>
  </section-card>
</template>

<style scoped lang="less"></style>
